#include <iostream>
#include <string>
#include <memory>


// 复杂产品：电脑(cpu+memory+disk)
class Computer
{
public:
    using ptr = std::shared_ptr<Computer>;
    void SetCPU(const std::string& cpu)
    {
        _cpu = cpu;
    }

    void SetMemory(const std::string& memory)
    {
        _memory = memory;
    }

    void SetDisk(const std::string& disk)
    {
        _disk = disk;
    }

    void Show()
    {
        std::cout << "电脑配置: "
                  << "\n\tCPU: " << _cpu
                  << "\n\tMemory: " << _memory
                  << "\n\tDisk: " << _disk
                  << std::endl;
    }

private:
    std::string _cpu;
    std::string _memory;
    std::string _disk;
};

// 抽象建造者：定义构建电脑各组件的接口
class ComputerBuilder
{
public:
    using ptr = std::shared_ptr<ComputerBuilder>;
    virtual void BuildCPU() = 0;
    virtual void BuildMemory() = 0;
    virtual void BuildDisk() = 0;
    virtual Computer::ptr GetResult() = 0;
    virtual ~ComputerBuilder() = default;
};

// 具体建造者1：游戏本建造者
class GamingComputerBuilder : public ComputerBuilder
{
public:
    GamingComputerBuilder()
    :_computer(std::make_shared<Computer>())
    {}
    void BuildCPU() override
    {
        _computer->SetCPU("Intel i9");
    }
    void BuildMemory() override
    {
        _computer->SetMemory("32GB DDR5");
    }
    void BuildDisk() override
    {
        _computer->SetDisk("1TB SSD");
    }
    Computer::ptr GetResult() override
    {
        return _computer;
    }

private:
    Computer::ptr _computer;
};

// 具体建造者2：办公本建造者
class OfficeComputerBuilder : public ComputerBuilder
{
public:
    OfficeComputerBuilder()
    :_computer(std::make_shared<Computer>())
    {}

    void BuildCPU() override
    {
        _computer->SetCPU("Intel i5");
    }
    void BuildMemory() override
    {
        _computer->SetMemory("16GB DDR4");
    }
    void BuildDisk() override
    {
        _computer->SetDisk("512GB SSD");
    }
    Computer::ptr GetResult() override
    {
        return _computer;
    }

private:
    Computer::ptr _computer;
};

// 指挥者：控制构建步骤
class Director
{
public:
    Director(ComputerBuilder::ptr computer_builder)
    :_computer_builder(computer_builder)
    {}

    void Construct()
    {
        _computer_builder->BuildCPU();
        _computer_builder->BuildMemory();
        _computer_builder->BuildDisk();
    }

private:
    ComputerBuilder::ptr _computer_builder;
};

int main()
{
    std::shared_ptr<ComputerBuilder> gaming_computer_builder = std::make_shared<GamingComputerBuilder>();
    std::shared_ptr<ComputerBuilder> office_computer_builder = std::make_shared<OfficeComputerBuilder>();

    std::unique_ptr<Director> gaming_computer_director = std::make_unique<Director>(gaming_computer_builder);
    std::unique_ptr<Director> office_computer_director = std::make_unique<Director>(office_computer_builder);

    gaming_computer_director->Construct();
    office_computer_director->Construct();

    Computer::ptr gaming_computer = gaming_computer_builder->GetResult();
    Computer::ptr office_computer = office_computer_builder->GetResult();

    gaming_computer->Show();
    office_computer->Show();
    
    return 0;
}